from kea2 import precondition, prob
from kea2.hypiumUtils import get_hierarchy, traverse_uiTree, get_bounds

import operator
import time
from typing import Dict
from unittest import TestCase


from kea2.hypiumDriver import HDriver, UiDriver
from kea2.keaUtils import max_tries
HDriver.initializer(device_sn="23E0224307001843")

    
class HiddenChecker:
    
    def __init__(self, window_size=None):
        self.capturedNode = None
        self.direction = None
        self.window_size = window_size
    
    def __call__(self, node_attrs) -> bool:
        
        bounds = get_bounds(node_attrs)
        
        passed = (
            bounds[0] >= 0
            and bounds[1] >= 0
            and bounds[2] <= self.window_size[0]
            and bounds[3] <= self.window_size[1]
        )
        
        if not passed:
            self.capturedNode = node_attrs
        
        return not passed
    
    def getCapturedNode(self):
        return self.capturedNode


class WidgetFinder:
    
    def __init__(self, rules: Dict):
        self.rules: Dict = rules
        self.target: Dict = None
    
    def __call__(self, node_attr: Dict) -> bool:
        for k, v in self.rules.items():
            if node_attr.get(k, "") != v:
                return False
        self.target = node_attr
        return True
    
    def getWidget(self) -> Dict:
        return self.target

    
class WidgetCollector:
    
    def __init__(self):
        self.widgets = dict()
    
    def __call__(self, node_attr: Dict) -> bool:
        if node_attr.get("bundleName") in {
            "com.ohos.sceneboard"
        }:
            return False
        if any([
            node_attr.get("key"),
            node_attr.get("text"),
            node_attr.get("id"),
            node_attr.get("description"),
        ]):
            node_repr = "|".join([
                f"id:{node_attr.get('id')}",
                f"key:{node_attr.get('key')}",
                f"text:{node_attr.get('text')}",
                f"description:{node_attr.get('description')}",
            ])

            self.widgets[node_repr] = get_bounds(node_attr)
        return False


def compare_hierarchy(before, after):
    wc1 = WidgetCollector()
    wc2 = WidgetCollector()
    traverse_uiTree(before, wc1)
    traverse_uiTree(after, wc2)
    before_wdigets = wc1.widgets
    after_widgets = wc2.widgets
    if len(before_wdigets) != len(after_widgets):
        print(f"Widget count mismatch: {len(before_wdigets)} vs {len(after_widgets)}")
        return False
    for w in before_wdigets.keys():
        if w not in after_widgets:
            print(f"Widget {w} disappeared")
            return False
        before_bounds = before_wdigets[w]
        after_bounds = after_widgets[w]
        if not (abs(_) < 10 for _ in list(map(operator.sub, before_bounds, after_bounds))):
            print(f"Widget {w} bounds changed: {before_bounds} -> {after_bounds}")
            return False
    return True


def scroll_to_bottom():
    d = HDriver.getScriptDriver()
    
    before_hierarchy = get_hierarchy()
    for _ in range(3):
        d.swipe(direction="UP")
        time.sleep(5)
        after_hierarchy = get_hierarchy()
        if compare_hierarchy(before_hierarchy, after_hierarchy):
            print("Scrolled to bottom")
            return True
        before_hierarchy = after_hierarchy
    return False


class HiddenTest(TestCase):

    d: "UiDriver"

    @prob(0.3)
    @max_tries(30)
    @precondition(lambda self: True)
    def test_hidden(self):
        """测试页面上是否存在隐藏控件
        """
        scroll_to_bottom()
        node = get_hierarchy()
        window_size = self.d.get_window_size()
        hiddenChecker = HiddenChecker(window_size=window_size)
        traverse_uiTree(node, hiddenChecker)
        assert hiddenChecker.capturedNode is None, "There is a hidden widget in the UI hierarchy"


if __name__ == "__main__":
    pass
    # d = HDriver.getScriptDriver()
    # scroll_to_bottom(d)
    # import sys
    # sys.exit(0)


    # json_node = get_hierarchy()
    # window_size = d.get_window_size()
    # hiddenChecker = HiddenChecker()
    # ans = traverse_uiTree(json_node, hiddenChecker)

    # widgetCollector = WidgetCollector()
    # traverse_uiTree(json_node, widgetCollector)
    # ws = widgetCollector.widgets


    # if ans:
    #     t = hiddenChecker.getCapturedNode()
    #     Aid = t["accessibilityId"]
    #     bounds = get_bounds(t)
        # c1 = tuple([
        #     (bounds[0] + bounds[2]) // 2,
        #     (bounds[1] + bounds[3]) // 2
        # ])
        # c2 = tuple([window_size[0] // 2, window_size[1] // 2])
        # d.swipe(direction="UP", distance=60)
        # d.drag()
